package com.xuelang.pipeline.app.task.impl;

import cn.hutool.core.util.IdUtil;
import com.xuelang.jadp.client.sys.dto.UserInfoDTO;
import com.xuelang.jadp.client.sys.dto.UserQueryDTO;
import com.xuelang.pipeline.app.task.TaskService;
import com.xuelang.pipeline.app.task.converter.TaskDTOToTaskConverter;
import com.xuelang.pipeline.client.common.constant.DictDTO;
import com.xuelang.pipeline.client.common.request.PageParam;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.client.common.util.BizAssert;
import com.xuelang.pipeline.client.common.util.UserContext;
import com.xuelang.pipeline.client.pipeline.enums.DeployStrategyEnum;
import com.xuelang.pipeline.client.pipeline.enums.RedLineInfoEnum;
import com.xuelang.pipeline.client.task.dto.DeployTaskConfigDTO;
import com.xuelang.pipeline.client.task.dto.TaskDTO;
import com.xuelang.pipeline.client.task.dto.TaskQuery;
import com.xuelang.pipeline.client.task.dto.TaskVerifyUserPageQuery;
import com.xuelang.pipeline.domain.pipeline.service.PipelineDomainService;
import com.xuelang.pipeline.domain.resource.service.ClusterDomainService;
import com.xuelang.pipeline.domain.task.Task;
import com.xuelang.pipeline.domain.task.service.TaskDomainService;
import com.xuelang.sys.app.sys.UserManagerService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 流水线任务服务实现类
 *
 * @author xiwen.zxg
 * @since 2024/5/15
 */
@Service
public class TaskServiceImpl implements TaskService {

    @Autowired
    TaskDomainService taskDomainService;
    @Autowired
    ClusterDomainService clusterDomainService;
    @Autowired
    UserManagerService userManagerService;

    @Autowired
    private PipelineDomainService pipelineDomainService;

    @Override
    public PageRecord<TaskDTO> pageList(PageParam<TaskQuery> dtoPageParam) {
        TaskQuery condition = dtoPageParam.getCondition();
        condition = condition == null ? new TaskQuery() : condition;
        PageRecord<Task> pageRecord = taskDomainService.pageList(
                dtoPageParam.getCurrentPage(),
                dtoPageParam.getPageSize(),
                condition);
        return new PageRecord<>(
                pageRecord.getCurrentPage(),
                pageRecord.getPageSize(),
                pageRecord.getTotalCount(),
                pageRecord.getTotalPages(),
                pageRecord.getRecords().stream().map(TaskDTOToTaskConverter.INSTANCE::taskToTaskDTO).collect(Collectors.toList()));
    }

    @Override
    public List<TaskDTO> list(TaskQuery taskQuery) {
        return taskDomainService.list(taskQuery).stream().map(TaskDTOToTaskConverter.INSTANCE::taskToTaskDTO).collect(Collectors.toList());
    }


    @Override
    public Boolean add(TaskDTO taskDTO) {
        BizAssert.notNull(taskDTO.getPipelineCode(), "流水线编码不能为空");
        BizAssert.notNull(taskDTO.getTaskDefUuid(), "任务定义唯一标识不能为空");
        BizAssert.notNull(taskDTO.getParentUuid(), "父任务唯一标识不能为空");
        BizAssert.notNull(taskDTO.getName(), "任务名称不能为空");
        BizAssert.notNull(taskDTO.getCode(), "任务编码不能为空");
        BizAssert.notNull(taskDTO.getParams(), "任务参数不能为空");
        BizAssert.notNull(taskDTO.getOutput(), "任务输出不能为空");
        BizAssert.notNull(taskDTO.getSortIndex(), "排序号不能为空");
        Task task = TaskDTOToTaskConverter.INSTANCE.taskDTOToTask(taskDTO);
        String userCode = UserContext.getCurrentUser().getCode();
        task.setUuid(IdUtil.fastSimpleUUID());
        task.setCreatorId(userCode);
        task.setUpdaterId(userCode);
        return taskDomainService.save(task);
    }

    @Override
    public Boolean update(TaskDTO taskDTO) {
        BizAssert.notNull(taskDTO.getUuid(), "任务唯一标识不能为空");
        BizAssert.notNull(taskDTO.getPipelineCode(), "流水线编码不能为空");
        BizAssert.notNull(taskDTO.getTaskDefUuid(), "任务定义唯一标识不能为空");
        BizAssert.notNull(taskDTO.getParentUuid(), "父任务唯一标识不能为空");
        BizAssert.notNull(taskDTO.getName(), "任务名称不能为空");
        BizAssert.notNull(taskDTO.getCode(), "任务编码不能为空");
        BizAssert.notNull(taskDTO.getParams(), "任务参数不能为空");
        BizAssert.notNull(taskDTO.getOutput(), "任务输出不能为空");
        BizAssert.notNull(taskDTO.getSortIndex(), "排序号不能为空");
        return taskDomainService.update(TaskDTOToTaskConverter.INSTANCE.taskDTOToTask(taskDTO));
    }

    @Override
    public Boolean delete(String uuid) {
        BizAssert.notNull(uuid, "uuid不能为空");
        return taskDomainService.delete(uuid);
    }

    @Override
    public TaskDTO query(String uuid) {
        BizAssert.notNull(uuid, "uuid不能为空");
        return TaskDTOToTaskConverter.INSTANCE.taskToTaskDTO(taskDomainService.query(uuid));
    }

    @Override
    public List<DictDTO> redLineTaskDict() {
        List<DictDTO> dtoList = new ArrayList<>();
        for (RedLineInfoEnum redLineInfo : RedLineInfoEnum.values()) {
            DictDTO dict = new DictDTO();
            dict.setId(redLineInfo.getKey());
            dict.setText(redLineInfo.getValue());
            dtoList.add(dict);
        }
        return dtoList;
    }

    @Override
    public String queryDeployAdvancedConfig(DeployTaskConfigDTO deployTaskConfigDTO) {
        String tmeplate = "components:\n" +
                "  - name: express-server\n" +
                "    type: webservice\n" +
                "    traits:\n" +
                "      - type: gateway\n" +
                "        properties:\n" +
                "          domain: {{domain}}\n" +
                "          http:\n" +
                "            \"/\": {{port}}\n" +
                "      - type: resource\n" +
                "        properties:\n" +
                "          cpu: {{cpu}}\n" +
                "          memory: {{memory}}Gi\n" +
                "          requests:\n" +
                "            cpu: {{cpu}}\n" +
                "            memory: {{memory}}Gi\n" +
                "          limits:\n" +
                "            cpu: {{cpu}}\n" +
                "            memory: {{memory}}Gi";
        String replace = tmeplate.replace("{{domain}}", deployTaskConfigDTO.getDomainName())
                .replace("{{port}}", deployTaskConfigDTO.getPort())
                .replace("{{cpu}}", deployTaskConfigDTO.getCpu())
                .replace("{{memory}}", deployTaskConfigDTO.getMemory());
        return replace;
    }

    @Override
    public PageRecord<DictDTO> queryVerifyUserDict(TaskVerifyUserPageQuery pageParam) {
        Long currentPage = Objects.isNull(pageParam.getCurrentPage()) ? 1 : pageParam.getCurrentPage();
        Long pageSize = Objects.isNull(pageParam.getPageSize()) ? 10 : pageParam.getPageSize();
        UserQueryDTO queryDTO = new UserQueryDTO();
        queryDTO.setRealName(pageParam.getQ());
        String idListStr = pageParam.getV();
        if (StringUtils.isNotBlank(idListStr)) {
            List<String> idList = Arrays.stream(idListStr.split(",")).collect(Collectors.toList());
            queryDTO.setUserIds(idList);
        }
        queryDTO.setPageSize(pageSize.intValue());
        queryDTO.setCurrentPage(currentPage.intValue());
        com.xuelang.jadp.client.sys.result.PageRecord<UserInfoDTO> userListPage = userManagerService.findUserListPage(queryDTO);
        if (userListPage.getTotalCount() == 0) {
            return new PageRecord<>(
                    currentPage,
                    pageSize,
                    0L,
                    0L,
                    null);
        }
        List<UserInfoDTO> userListPageRecords = userListPage.getRecords();
        List<DictDTO> result = userListPageRecords.stream().map(this::transitUserInfoToDict).collect(Collectors.toList());
        return new PageRecord<>(
                currentPage,
                pageSize,
                userListPage.getTotalCount(),
                userListPage.getTotalPages(),
                result);
    }

    @Override
    public List<DictDTO> queryDeployTaskDict() {
        List<DictDTO> dtoList = new ArrayList<>();
        for (DeployStrategyEnum strategyEnum : DeployStrategyEnum.values()) {
            DictDTO dict = new DictDTO();
            dict.setId(strategyEnum.getKey().toString());
            dict.setText(strategyEnum.getValue());
            dtoList.add(dict);
        }
        return dtoList;
    }

    private DictDTO transitUserInfoToDict(UserInfoDTO userInfoDTO) {
        DictDTO result = new DictDTO();
        result.setId(userInfoDTO.getUserId());
        result.setText(userInfoDTO.getRealName());
        return result;
    }

}
